package config

import (
	"context"
	"fmt"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
)

// 上传渠道
type (
	// UploadConfigItem 上传配置属性
	UploadConfigItem struct {
		StorageType string                 `json:"storage_type" dc:"存储类型"`
		UploadExt   string                 `json:"upload_ext"  dc:"允许上传扩展"`
		Config      map[string]interface{} `json:"config" dc:"配置内容"`
	}

	// UploadConfigLocalItem 本地上传配置
	UploadConfigLocalItem struct {
		StorageType string `json:"storage_type" dc:"存储类型"`
		Root        string `json:"root" dc:"上传根目录"`
		Path        string `json:"url" dc:"上传附件地址"`
		FileExt     string `json:"file_ext" dc:"文件上传控制"`
	}
)

const (
	ConfigUploads      = `uploads`
	ConfigUploadsLocal = `local`
)

// GetUploadsConfig 获取上传配置
func (c *sConfig) GetUploadsConfig(ctx context.Context) (item *UploadConfigItem, err error) {
	// 初始化
	item = &UploadConfigItem{}
	defer func() {
		if err != nil {
			g.Log().Error(ctx, "GetUploads", "failed to initialize upload config", "error", err)
		}
	}()

	// 初始化读取原始配置
	rawConfig, err := g.Cfg().Get(ctx, ConfigUploads)
	if err != nil {
		return nil, err
	}

	// 原始配置转换为MAP
	uploadConfig := rawConfig.Map()
	if len(uploadConfig) == 0 {
		return nil, gerror.New("缺少Upload配置")
	}

	// 取出Upload配置详情通道
	storesRaw, ok := uploadConfig["stores"]
	if !ok {
		return nil, gerror.New("Upload配置详情配置缺失")
	}

	// 获取原始配置详情
	stores, ok := storesRaw.(map[string]interface{})
	if !ok {
		return nil, gerror.New("Upload配置详情类型错误，应为map[string]interface{}")
	}

	// 原始存储通道类型
	storageTypeRaw, ok := uploadConfig["driver"]
	if !ok {
		return nil, gerror.New("缺少上传存储类型配置")
	}

	// 格式化字符串
	item.StorageType, ok = storageTypeRaw.(string)
	if !ok {
		return nil, gerror.New("上传存储类型配置应为字符串类型")
	}

	// 原始上传扩展
	uploadExtRaw, ok := uploadConfig["uploadExt"]
	if !ok {
		return nil, gerror.New(`请设置文件上传后缀扩展`)
	}

	// 格式化上传扩展
	item.UploadExt, ok = uploadExtRaw.(string)
	if !ok {
		return nil, gerror.New(`文件上传后缀格式错误`)
	}

	// 配置详情
	detailRaw, ok := stores[item.StorageType]
	if !ok {
		return nil, gerror.New(fmt.Sprintf("缺少%s配置信息", item.StorageType))
	}

	// 详情断言
	item.Config, ok = detailRaw.(map[string]interface{})
	if !ok {
		return nil, gerror.New(fmt.Sprintf("%s配置详情类型错误，应为map[string]interface{}", item.StorageType))
	}

	return
}

// ParseUploadConfigRaw 解析上传配置详情
func (c *sConfig) ParseUploadConfigRaw(ctx context.Context, options interface{}) error {
	rawConfig, err := c.GetUploadsConfig(ctx)
	if err != nil {
		return err
	}
	return gconv.Struct(rawConfig.Config, options)
}

// GetLocalUploadConfig 读取本地配置
func (c *sConfig) GetLocalUploadConfig(ctx context.Context) (localRaw *UploadConfigLocalItem, err error) {
	localRaw = &UploadConfigLocalItem{}
	err = c.ParseUploadConfigRaw(ctx, &localRaw)
	if err != nil {
		return nil, err
	}
	return localRaw, nil
}
